#include "ili9341.h"
#include "stm32f10x_conf.h"


uint16_t LCD_X_LENGTH = ILI9341_LESS_PIXEL;
uint16_t LCD_Y_LENGTH = ILI9341_MORE_PIXEL;

static uint8_t LCD_SCAN_MODE = 6;

static sFont *LCD_CurrentFonts = &Font8x16;			// 当前LCD显示字体
static uint16_t CurrentBackColor = WHITE;			// 当前LCD显示背景颜色
static uint16_t CurrentTextColor = BLACK;			// 当前LCD显示字体颜色

static void ILI9341_Delay(__IO uint32_t nCount)
{
    for(; nCount != 0; nCount--);
}

// 向ILI9341写指令
void ILI9341_Write_Cmd(uint16_t usCmd)
{
    *(__IO uint16_t *)(FSMC_ADDR_ILI9341_CMD) = usCmd;
}

// 向ILI9341写数据
void ILI9341_Write_Data(uint16_t usData)
{
    *(__IO uint16_t *)(FSMC_ADDR_ILI9341_DATA) = usData;
}

uint16_t ILI9341_Read_Data(void)
{
	return (*(__IO uint16_t *)(FSMC_ADDR_ILI9341_DATA));
}

// LCD液晶屏GPIO配置
static void ILI9341_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* 开启GPIO时钟信号 */
    RCC_APB2PeriphClockCmd(
        /* 控制信号 */
        ILI9341_CS_CLK|ILI9341_DC_CLK|ILI9341_WR_CLK|
        ILI9341_RD_CLK|ILI9341_RST_CLK|ILI9341_BK_CLK|
        /* 数据信号*/
         ILI9341_D0_CLK|ILI9341_D1_CLK|ILI9341_D2_CLK|ILI9341_D3_CLK|
         ILI9341_D4_CLK|ILI9341_D5_CLK|ILI9341_D6_CLK|ILI9341_D7_CLK|
         ILI9341_D8_CLK|ILI9341_D9_CLK|ILI9341_D10_CLK|ILI9341_D11_CLK|
         ILI9341_D12_CLK|ILI9341_D13_CLK|ILI9341_D14_CLK|ILI9341_D15_CLK,
         ENABLE);

    /* 数据信号GPIO初始化 */ 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	
	GPIO_InitStructure.GPIO_Pin = ILI9341_D0_PIN;
	GPIO_Init(ILI9341_D0_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D1_PIN;
	GPIO_Init(ILI9341_D1_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D2_PIN;
	GPIO_Init(ILI9341_D2_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D3_PIN;
	GPIO_Init(ILI9341_D3_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D4_PIN;
	GPIO_Init(ILI9341_D4_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D5_PIN;
	GPIO_Init(ILI9341_D5_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D6_PIN;
	GPIO_Init(ILI9341_D6_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D7_PIN;
	GPIO_Init(ILI9341_D7_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D8_PIN;
	GPIO_Init(ILI9341_D8_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D9_PIN;
	GPIO_Init(ILI9341_D9_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D10_PIN;
	GPIO_Init(ILI9341_D10_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D11_PIN;
	GPIO_Init(ILI9341_D11_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D12_PIN;
	GPIO_Init(ILI9341_D12_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D13_PIN;
	GPIO_Init(ILI9341_D13_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D14_PIN;
	GPIO_Init(ILI9341_D14_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_D15_PIN;
	GPIO_Init(ILI9341_D15_PORT, &GPIO_InitStructure);


    /* 配置FSMC相对应的控制信号 
    ** FSMC_NOE: LCD_RD
    ** FSMC_NWE: LCD_WR
    ** FSMC_NE1: LCD_CS
    ** FSMC_A16: LCD_DC
    */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

	GPIO_InitStructure.GPIO_Pin = ILI9341_CS_PIN;
	GPIO_Init(ILI9341_CS_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_DC_PIN;
	GPIO_Init(ILI9341_DC_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_WR_PIN;
	GPIO_Init(ILI9341_WR_PORT, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = ILI9341_RD_PIN;
	GPIO_Init(ILI9341_RD_PORT, &GPIO_InitStructure);

    /* 配置背光灯GPIO引脚 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = ILI9341_BK_PIN;
    GPIO_Init(ILI9341_BK_PORT, &GPIO_InitStructure );

    /* 配置复位GPIO引脚 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = ILI9341_RST_PIN;
    GPIO_Init(ILI9341_RST_PORT, &GPIO_InitStructure );
    
}

// FSMC总线配置
static void ILI9341_FSMC_Config(void)
{
    FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTimingInitSturcture;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

    FSMC_NORSRAMTimingInitSturcture.FSMC_AddressSetupTime 		= 0x01;           		// 地址建立时间
    FSMC_NORSRAMTimingInitSturcture.FSMC_DataSetupTime 			= 0X04;              	// 数据建立时间
    FSMC_NORSRAMTimingInitSturcture.FSMC_AccessMode 			= FSMC_AccessMode_B;    // 选择控制模式
    FSMC_NORSRAMTimingInitSturcture.FSMC_AddressHoldTime 		= 0x00;            		// 地址保持时间
    FSMC_NORSRAMTimingInitSturcture.FSMC_BusTurnAroundDuration 	= 0x00;     			// 设置总线转换周期
    FSMC_NORSRAMTimingInitSturcture.FSMC_CLKDivision 			= 0x00;                	// 设置时钟分频
    FSMC_NORSRAMTimingInitSturcture.FSMC_DataLatency 			= 0x00;                	// 数据保持时间

    FSMC_NORSRAMInitStructure.FSMC_Bank 			= FSMC_BANK1_NORSRAMX;             	// 设置存储区域
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux 	= FSMC_DataAddressMux_Disable;    
    FSMC_NORSRAMInitStructure.FSMC_MemoryType 		= FSMC_MemoryType_NOR;            	// 存储器类型
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth 	= FSMC_MemoryDataWidth_16b;  		// 数据线宽度
    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode 			= FSMC_BurstAccessMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity 		= FSMC_WaitSignalPolarity_Low;
    FSMC_NORSRAMInitStructure.FSMC_WrapMode 				= FSMC_WrapMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive 		= FSMC_WaitSignalActive_BeforeWaitState;
    FSMC_NORSRAMInitStructure.FSMC_WriteOperation 			= FSMC_WriteOperation_Enable;     // 写使能
    FSMC_NORSRAMInitStructure.FSMC_WaitSignal 				= FSMC_WaitSignal_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode 			= FSMC_ExtendedMode_Disable;
    FSMC_NORSRAMInitStructure.FSMC_WriteBurst 				= FSMC_WriteBurst_Disable;
    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct 	= &FSMC_NORSRAMTimingInitSturcture;
    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct 		= &FSMC_NORSRAMTimingInitSturcture;

    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
    FSMC_NORSRAMCmd(FSMC_BANK1_NORSRAMX,ENABLE);

}


static void ILI9341_REG_Config ( void )
{
	/*  Power control B (CFh)  */
	ILI9341_Write_Cmd(0xCF);
	ILI9341_Write_Data(0x00);
	ILI9341_Write_Data(0x81);
	ILI9341_Write_Data(0x30);
	
	/*  Power on sequence control (EDh) */
	ILI9341_Write_Cmd (0xED);
	ILI9341_Write_Data (0x64);
	ILI9341_Write_Data ( 0x03 );
	ILI9341_Write_Data ( 0x12 );
	ILI9341_Write_Data ( 0x81 );
	
	/*  Driver timing control A (E8h) */
	ILI9341_Write_Cmd ( 0xE8 );
	ILI9341_Write_Data ( 0x85 );
	ILI9341_Write_Data ( 0x10 );
	ILI9341_Write_Data ( 0x78 );
	
	/*  Power control A (CBh) */
	ILI9341_Write_Cmd ( 0xCB );
	ILI9341_Write_Data ( 0x39 );
	ILI9341_Write_Data ( 0x2C );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x34 );
	ILI9341_Write_Data ( 0x02 );
	
	/* Pump ratio control (F7h) */

	ILI9341_Write_Cmd ( 0xF7 );
	ILI9341_Write_Data ( 0x20 );
	
	/* Driver timing control B */

	ILI9341_Write_Cmd ( 0xEA );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	
	/* Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
	ILI9341_Write_Cmd ( 0xB1 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x1B );
	
	/*  Display Function Control (B6h) */
	ILI9341_Write_Cmd ( 0xB6 );
	ILI9341_Write_Data ( 0x0A );
	ILI9341_Write_Data ( 0xA2 );
	
	/* Power Control 1 (C0h) */

	ILI9341_Write_Cmd ( 0xC0 );
	ILI9341_Write_Data ( 0x35 );
	
	/* Power Control 2 (C1h) */

	ILI9341_Write_Cmd ( 0xC1 );
	ILI9341_Write_Data ( 0x11 );
	
	/* VCOM Control 1 (C5h) */
	ILI9341_Write_Cmd ( 0xC5 );
	ILI9341_Write_Data ( 0x45 );
	ILI9341_Write_Data ( 0x45 );
	
	/*  VCOM Control 2 (C7h)  */
	ILI9341_Write_Cmd ( 0xC7 );
	ILI9341_Write_Data ( 0xA2 );
	
	/* Enable 3G (F2h) */
	ILI9341_Write_Cmd ( 0xF2 );
	ILI9341_Write_Data ( 0x00 );
	
	/* Gamma Set (26h) */
	ILI9341_Write_Cmd ( 0x26 );
	ILI9341_Write_Data ( 0x01 );	

	
	/* Positive Gamma Correction */
	ILI9341_Write_Cmd ( 0xE0 ); //Set Gamma
	ILI9341_Write_Data ( 0x0F );
	ILI9341_Write_Data ( 0x26 );
	ILI9341_Write_Data ( 0x24 );
	ILI9341_Write_Data ( 0x0B );
	ILI9341_Write_Data ( 0x0E );
	ILI9341_Write_Data ( 0x09 );
	ILI9341_Write_Data ( 0x54 );
	ILI9341_Write_Data ( 0xA8 );
	ILI9341_Write_Data ( 0x46 );
	ILI9341_Write_Data ( 0x0C );
	ILI9341_Write_Data ( 0x17 );
	ILI9341_Write_Data ( 0x09 );
	ILI9341_Write_Data ( 0x0F );
	ILI9341_Write_Data ( 0x07 );
	ILI9341_Write_Data ( 0x00 );
	
	/* Negative Gamma Correction (E1h) */
	ILI9341_Write_Cmd ( 0XE1 ); //Set Gamma
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x19 );
	ILI9341_Write_Data ( 0x1B );
	ILI9341_Write_Data ( 0x04 );
	ILI9341_Write_Data ( 0x10 );
	ILI9341_Write_Data ( 0x07 );
	ILI9341_Write_Data ( 0x2A );
	ILI9341_Write_Data ( 0x47 );
	ILI9341_Write_Data ( 0x39 );
	ILI9341_Write_Data ( 0x03 );
	ILI9341_Write_Data ( 0x06 );
	ILI9341_Write_Data ( 0x06 );
	ILI9341_Write_Data ( 0x30 );
	ILI9341_Write_Data ( 0x38 );
	ILI9341_Write_Data ( 0x0F );
	
	/* memory access control set */

	ILI9341_Write_Cmd ( 0x36 ); 	
	ILI9341_Write_Data ( 0xC8 );    /*竖屏  左上角到 (起点)到右下角 (终点)扫描方式*/

	
	/* column address control set */
	ILI9341_Write_Cmd ( CMD_SetCoordinateX ); 
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0xEF );
	
	/* page address control set */

	ILI9341_Write_Cmd ( CMD_SetCoordinateY ); 
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x00 );
	ILI9341_Write_Data ( 0x01 );
	ILI9341_Write_Data ( 0x3F );
	
	/*  Pixel Format Set (3Ah)  */

	ILI9341_Write_Cmd ( 0x3a ); 
	ILI9341_Write_Data ( 0x55 );
	
	/* Sleep Out (11h)  */
	ILI9341_Write_Cmd ( 0x11 );	
	ILI9341_Delay ( 0xAFFf<<2 ); 	

	
	/* Display ON (29h) */
	ILI9341_Write_Cmd ( 0x29 ); 
	
}

// 背光灯控制
void ILI9341_BackLed_Control(FunctionalState enumState)
{
    if(ENABLE == enumState)
    {
        GPIO_ResetBits(ILI9341_BK_PORT,ILI9341_BK_PIN);
    }
    else
    {
        GPIO_SetBits(ILI9341_BK_PORT,ILI9341_BK_PIN);
    }
}

// LCD复位
void ILI9341_Rst(void)
{
	GPIO_ResetBits(ILI9341_RST_PORT,ILI9341_RST_PIN);
	ILI9341_Delay ( 0xAFF ); 	
//	delay_us(100);

	GPIO_SetBits(ILI9341_RST_PORT, ILI9341_RST_PIN);
	ILI9341_Delay ( 0xAFF ); 	
//	delay_us(100);
}

// LCD初始化
void ILI9341_Init(void)
{
    ILI9341_GPIO_Config();
    ILI9341_FSMC_Config();

	ILI9341_BackLed_Control(ENABLE);
	ILI9341_Rst();

	ILI9341_REG_Config();
	ILI9341_GramScan(LCD_SCAN_MODE);

}

/***************************************************************************************************
** Function name:           ILI9341_GramScan
** Descriptions:            设置ILI9341的GRAM的扫描方向
** input parameters:        ucOption：选择GRAM的扫描方向
**							0~7：参数可选值为0~7这八个方向
**							0,3,5,6模式适合从左往右显示文字
**
**							其中0,2,4,6模式X方向像素为240，Y方向像素为320
**							其中1,3,5,7模式X方向像素为320，Y方向像素为240
------------------------------------------------------------
 模式0：					 .			模式1			 .		模式2：				  .	模式3：					
					A		.					A		.		A					.		A									
					|		.					|		.		|					.		|							
					Y		.					X		.		Y					.		X					
					0		.					1		.		2					.		3					
			<--- X0 o		.			<----Y1	o		.		o 2X--->  			.		o 3Y--->	
------------------------------------------------------------	
	模式4：					 .	模式5：					 .	模式6：			     	 .	模式7：				
			<--- X4 o		.			<--- Y5 o		.		o 6X--->  			.		o 7Y--->	
					4		.					5		.		6					.		7	
					Y		.					X		.		Y					.		X						
					|		.					|		.		|					.		|							
					V		.					V		.		V					.		V		
---------------------------------------------------------			

** output parameters:      	
** Returned value:          none
** Created by:              zheh.zhang
** Created date:            2021-02-24
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_GramScan(uint8_t ucOption)
{
	// 参数检测，只可输入0~7
	if(ucOption > 7)
		return;

	LCD_SCAN_MODE = ucOption;

	/* 选择XY方向像素宽度 */
	if(ucOption%2 == 0)
	{
		LCD_X_LENGTH = ILI9341_LESS_PIXEL;
		LCD_Y_LENGTH = ILI9341_MORE_PIXEL;
	}
	else
	{
		LCD_X_LENGTH = ILI9341_MORE_PIXEL;
		LCD_Y_LENGTH = ILI9341_LESS_PIXEL;
	}

	/* 设置GRAM扫描方向 */
	ILI9341_Write_Cmd(0X36);
	ILI9341_Write_Data(0X08 |(ucOption << 5));

	/* 设置X方向长度 */
	ILI9341_Write_Cmd(CMD_SetCoordinateX);
	ILI9341_Write_Data(0X00);	// X起始坐标高8位
	ILI9341_Write_Data(0X00);	// X起始坐标低8位
	ILI9341_Write_Data(((LCD_X_LENGTH-1)>>8)&0XFF);	// X结束坐标高8位
	ILI9341_Write_Data((LCD_X_LENGTH-1)&0X00FF);	// X结束坐标低8位

	/* 设置Y方向长度 */
	ILI9341_Write_Cmd(CMD_SetCoordinateY);
	ILI9341_Write_Data(0X00);	// Y起始坐标高8位
	ILI9341_Write_Data(0X00);	// Y起始坐标低8位
	ILI9341_Write_Data(((LCD_Y_LENGTH-1)>>8)&0XFF);	// Y结束坐标高8位
	ILI9341_Write_Data((LCD_Y_LENGTH-1)&0X00FF);	// Y结束坐标高8位

	/* 设置像素点 */
	ILI9341_Write_Cmd(CMD_SetPixel);
}

/***************************************************************************************************
** Function name:           ILI9341_OpenWindow
** Descriptions:            在液晶上创建一个显示窗口
** input parameters:        usX：X起始坐标
							usY：Y起始坐标
							usWidth：屏幕宽度
							usHeigth：屏幕高度
** output parameters:      	
** Returned value:          none
** Created by:              zheh.zhang
** Created date:            2021-02-24
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_OpenWindow(uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeigth)
{
	ILI9341_Write_Cmd(CMD_SetCoordinateX);
	ILI9341_Write_Data(usX>>8);
	ILI9341_Write_Data(usX&0XFF);
	ILI9341_Write_Data((usX + usWidth - 1)>>8);
	ILI9341_Write_Data((usX + usWidth - 1)&0XFF);

	ILI9341_Write_Cmd(CMD_SetCoordinateY);
	ILI9341_Write_Data(usY>>8);
	ILI9341_Write_Data(usY&0XFF);
	ILI9341_Write_Data((usY + usHeigth - 1)>>8);
	ILI9341_Write_Data((usY + usHeigth - 1)&0XFF);
}

/***************************************************************************************************
** Function name:           ILI9341_SetCursor
** Descriptions:            设置当前光标
** input parameters:        usX：X坐标位置
							usY：Y坐标位置
							usWidth：屏幕宽度
							usHeigth：屏幕高度
** output parameters:      	
** Returned value:          none
** Created by:              zheh.zhang
** Created date:            2021-03-14
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_SetCursor(uint16_t usX,uint16_t usY)
{
	ILI9341_OpenWindow(usX, usY, 1, 1);
}

/***************************************************************************************************
** Function name:           ILI9341_FillColor
** Descriptions:            填充区域颜色
** input parameters:        ulAmout_point：要填充颜色的像素点的总数目
							usColor：颜色
** output parameters:      	
** Returned value:          none
** Created by:              zheh.zhang
** Created date:            2021-03-14
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
static __INLINE void ILI9341_FillColor(uint32_t ulAmout_point, uint32_t usColor)
{
	uint32_t i = 0;

	ILI9341_Write_Cmd(CMD_SetPixel);

	for(i=0; i<ulAmout_point; i++)
	{
		ILI9341_Write_Data(usColor);
	}
}

/***************************************************************************************************
** Function name:           ILI9341_Clear
** Descriptions:            对屏幕某款区域进行清屏
** input parameters:        usX：X坐标位置
							usY：Y坐标位置
							usWidth：屏幕宽度
							usHeigth：屏幕高度
** output parameters:      	
** Returned value:          none
** Created by:              zheh.zhang
** Created date:            2021-03-10
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_Clear(uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight)
{
	ILI9341_OpenWindow(usX,usY,usWidth,usHeight);
	ILI9341_FillColor(usWidth*usHeight, CurrentBackColor);
}

/***************************************************************************************************
** Function name:           ILI9341_SetPointPixel
** Descriptions:            显示屏上的某一点像素点一某种颜色显示
** input parameters:        usX：X坐标位置
							usY：Y坐标位置
** output parameters:      	
** Returned value:          none
** Created by:              zheh.zhang
** Created date:            2021-04-17
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_SetPointPixel(uint16_t usX, uint16_t usY)
{
	if((usX < LCD_X_LENGTH)&&(usY < LCD_Y_LENGTH))
	{
		ILI9341_SetCursor(usX, usY);
		ILI9341_FillColor(1, CurrentTextColor);
	}
}

/***************************************************************************************************
** Function name:           ILI9341_Read_PixelData
** Descriptions:            读取ILI9341像素点数据
** input parameters:        none
** output parameters:      	none
** Returned value:          none
** Created by:              zheh.zhang
** Created date:            2021-04-17
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
static uint16_t ILI9341_Read_PixelData(void)
{
	uint16_t usR=0;
	uint16_t usG=0; 
	uint16_t usB=0;

	ILI9341_Write_Cmd(0x2E);	// 读数据

	usR = ILI9341_Read_Data();	// 第一个数据为空

	usR = ILI9341_Read_Data();
	usB = ILI9341_Read_Data();
	usG = ILI9341_Read_Data();

	return (((usR >> 11)<<11) | ((usG >> 10) << 5) | (usB>>11));
}

/***************************************************************************************************
** Function name:           ILI9341_GetPointPixel
** Descriptions:            读取显示屏某一个坐标点像素点数据
** input parameters:        usX：X坐标位置
							usY：Y坐标位置
** output parameters:      	
** Returned value:          像素数据
** Created by:              zheh.zhang
** Created date:            2021-04-17
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
uint16_t ILI9341_GetPointPixel(uint16_t usX, uint16_t usY)
{
	uint16_t usPixelData;

	ILI9341_SetCursor(usX, usY);

	usPixelData = ILI9341_Read_PixelData();

	return usPixelData;
}

/***************************************************************************************************
** Function name:           ILI9341_DrawLine
** Descriptions:            在液晶上画直线
** input parameters:        usX1：X起点坐标位置
							usY1：Y起点坐标位置
							usX2：X结束坐标位置
							usY2：Y结束坐标位置
** output parameters:      	
** Returned value:          
** Created by:              zheh.zhang
** Created date:            2021-04-18
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_DrawLine(uint16_t usX1, uint16_t usY1, uint16_t usX2, uint16_t usY2)
{
	uint16_t us;
	uint16_t usX_Current; 
	uint16_t usY_Current;

	int32_t lError_X = 0;
	int32_t lError_Y = 0;
	int32_t lDelta_X;
	int32_t lDelta_Y;
	int32_t lDistance;

	int32_t lIncrease_X;
	int32_t lIncrease_Y;

	/* 计算坐标增量 */
	lDelta_X = usX2 - usX1;	// 计算X轴坐标增量
	lDelta_Y = usY2 - usY1; // 计算X轴坐标增量

	/* 当前坐标 */
	usX_Current = usX1;
	usY_Current = usY1;

	if(lDelta_X > 0)
	{
		lIncrease_X = 1;	// 坐标移动步长
	}
	else if(lDelta_X == 0)
	{
		lIncrease_X = 0;
	}
	else
	{
		lIncrease_X = -1;
		lDelta_X = -lDelta_X;
	}

	if(lDelta_Y > 0)
	{
		lIncrease_Y = 1;
	}
	else if(lDelta_Y == 0)
	{
		lIncrease_Y = 0;
	}
	else
	{
		lIncrease_Y = -1;
		lDelta_Y = -lDelta_Y;
	}

	// 设置最长距离
	if(lDelta_X > lDelta_Y)
	{
		lDistance = lDelta_X;
	}
	else
	{
		lDistance = lDelta_Y;
	}

	for(us=0; us < lDistance+1; us++)
	{
		ILI9341_SetPointPixel(usX_Current, usY_Current);

		lError_X += lDelta_X;
		lError_Y += lDelta_Y;

		if(lError_X > lDistance)
		{
			lError_X -= lDistance;
			usX_Current += lIncrease_X;
		}

		if(lError_Y > lDistance)
		{
			lError_Y -= lDistance;
			usY_Current += lIncrease_Y;
		}
	}
}

/***************************************************************************************************
** Function name:           ILI9341_DrawRectangle
** Descriptions:            在液晶上画矩形
** input parameters:        usX_Start：X起点坐标位置
							usY_Start：Y起点坐标位置
							usWidth：矩形宽度
							usHeight：矩形高度
							ucFilled：是否填充该矩形
							0：不填充
							1：填充
** output parameters:      	
** Returned value:          
** Created by:              zheh.zhang
** Created date:            2021-04-18
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_DrawRectangle(uint16_t usX_Start, uint16_t usY_Start, uint16_t usWidth, uint16_t usHeight, uint8_t ucFilled)
{
	if(ucFilled)
	{
		ILI9341_OpenWindow(usX_Start, usY_Start, usWidth, usHeight);
		ILI9341_FillColor(usWidth * usHeight, CurrentTextColor);
	}
	else
	{
		ILI9341_DrawLine(usX_Start,usY_Start,usX_Start+usWidth-1, usY_Start);
		ILI9341_DrawLine(usX_Start, usY_Start, usX_Start, usY_Start+usHeight-1);
		ILI9341_DrawLine(usX_Start, usY_Start+usHeight-1, usX_Start+usWidth-1, usY_Start+usHeight-1);
		ILI9341_DrawLine(usX_Start+usWidth-1, usY_Start, usX_Start+usWidth-1, usY_Start+usHeight-1);
	}
}

/***************************************************************************************************
** Function name:           ILI9341_DrawCircle
** Descriptions:            在液晶上画矩形
** input parameters:        usX_Start：X起点坐标位置
							usY_Start：Y起点坐标位置
							usWidth：矩形宽度
							usHeight：矩形高度
							ucFilled：是否填充该矩形
							0：不填充
							1：填充
** output parameters:      	
** Returned value:          
** Created by:              zheh.zhang
** Created date:            2021-04-18
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_DrawCircle(uint16_t usX_Center, uint16_t usY_Center, uint16_t usRadius, uint16_t ucFilled)
{
	int16_t sCurrentX;
	int16_t sCurrentY;
	int16_t sError;
	int16_t sCountY;

	sCurrentX = 0;
	sCurrentY = usRadius;

	sError = 3 - (usRadius << 1);

	while(sCurrentX <= sCurrentY)
	{
		if(ucFilled)
		{
			for(sCountY = sCurrentX; sCountY <= sCurrentY; sCountY++)
			{
				ILI9341_SetPointPixel(usX_Center + sCurrentX, usY_Center + sCountY);
				ILI9341_SetPointPixel(usX_Center - sCurrentX, usY_Center + sCountY);
				ILI9341_SetPointPixel(usX_Center - sCountY, usY_Center + sCurrentX);
				ILI9341_SetPointPixel(usX_Center - sCountY, usY_Center - sCurrentX);
				ILI9341_SetPointPixel(usX_Center - sCurrentX, usY_Center - sCountY);
				ILI9341_SetPointPixel(usX_Center + sCurrentX, usY_Center - sCountY);
				ILI9341_SetPointPixel(usX_Center + sCountY, usY_Center - sCurrentX);
				ILI9341_SetPointPixel(usX_Center + sCountY,usY_Center +  sCurrentX);
			}
		}
		else
		{
			ILI9341_SetPointPixel(usX_Center + sCurrentX, usY_Center + sCurrentY);
			ILI9341_SetPointPixel(usX_Center - sCurrentX, usY_Center + sCurrentY);
			ILI9341_SetPointPixel(usX_Center - sCurrentY, usY_Center + sCurrentX);
			ILI9341_SetPointPixel(usX_Center - sCurrentY, usY_Center - sCurrentX);
			ILI9341_SetPointPixel(usX_Center - sCurrentX, usY_Center - sCurrentY);
			ILI9341_SetPointPixel(usX_Center + sCurrentX, usY_Center - sCurrentY);
			ILI9341_SetPointPixel(usX_Center + sCurrentY, usY_Center - sCurrentX);
			ILI9341_SetPointPixel(usX_Center + sCurrentY, usY_Center + sCurrentX);
		}

		sCurrentX++;

		if(sError < 0)
		{
			sError += 4*sCurrentX + 6;
		}
		else
		{
			sError += 10 + 4 * (sCurrentX - sCurrentY);
			sCurrentY--;
		}
	}
}

/***************************************************************************************************
** Function name:           ILI9341_DrawCircle
** Descriptions:            在液晶上显示一个英文字符
** input parameters:        usX：字符的起始X坐标
							usY：字符的起始Y坐标
							char: 要显示的英文字符
** Returned value:          
** Created by:              zheh.zhang
** Created date:            2021-04-23
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_DispChar_EN(uint16_t usX, uint16_t usY, const char cChar)
{
	uint8_t byteCount, bitCount,fontLength;
	uint16_t ucRelativePosition;
	uint8_t *pFont;

	ucRelativePosition = cChar - ' ';

	fontLength = (LCD_CurrentFonts->width * LCD_CurrentFonts->height)/8;

	pFont = (uint8_t *)&LCD_CurrentFonts->table[ucRelativePosition * fontLength];

	ILI9341_OpenWindow(usX, usY, LCD_CurrentFonts->width, LCD_CurrentFonts->height);

	ILI9341_Write_Cmd(CMD_SetPixel);

	for(byteCount = 0; byteCount < fontLength; byteCount++)
	{
		for(bitCount = 0; bitCount < 8; bitCount++)
		{
			if(pFont[byteCount] & (0x80>>bitCount))
			{
				ILI9341_Write_Data(CurrentTextColor);
			}
			else
			{
				ILI9341_Write_Data(CurrentBackColor);
			}
		}
	}
}

/***************************************************************************************************
** Function name:           ILI9341_DispStringLine_EN
** Descriptions:            在液晶上显示一行字符串
** input parameters:        line：要显示的行
							pStr: 要显示的字符串
** Returned value:          
** Created by:              zheh.zhang
** Created date:            2021-04-24
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_DispStringLine_EN(uint16_t line, char *pStr)
{
	uint16_t usX = 0;

	while (*pStr != '\0')
	{
		if((usX - ILI9341_DispWindow_X_Star + LCD_CurrentFonts->width) > LCD_X_LENGTH)
		{
			usX = ILI9341_DispWindow_X_Star;
			line += LCD_CurrentFonts->height;
		}

		if((line - ILI9341_DispWindow_Y_Star + LCD_CurrentFonts->height) > LCD_Y_LENGTH)
		{
			usX = ILI9341_DispWindow_X_Star;
			line = ILI9341_DispWindow_Y_Star;
		}

		ILI9341_DispChar_EN(usX, line, *pStr);

		pStr++;

		usX += LCD_CurrentFonts->width;
	}
}

/***************************************************************************************************
** Function name:           ILI9341_DispString_EN
** Descriptions:            在液晶上某一位置显示一行字符串
** input parameters:        usX：字符的起始X坐标
							usY：字符的起始Y坐标
							pStr: 要显示的字符串
** Returned value:          
** Created by:              zheh.zhang
** Created date:            2021-04-24
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_DispString_EN(uint16_t usX, uint16_t usY, char *pStr)
{
	while(*pStr != '\0')
	{
		if((usX - ILI9341_DispWindow_X_Star + LCD_CurrentFonts->width) > LCD_X_LENGTH)
		{
			usX = ILI9341_DispWindow_X_Star;
			usY += LCD_CurrentFonts->height;
		}

		if((usY - ILI9341_DispWindow_Y_Star + LCD_CurrentFonts->height) > LCD_Y_LENGTH)
		{
			usX = ILI9341_DispWindow_X_Star;
			usY = ILI9341_DispWindow_Y_Star;
		}

		ILI9341_DispChar_EN(usX, usY, *pStr);

		pStr++;

		usX += LCD_CurrentFonts->width;
	}
}

/***************************************************************************************************
** Function name:           ILI9341_DispString_EN_YDir
** Descriptions:            在液晶上某一位置显示一行字符串(沿Y轴方向)
** input parameters:        usX：字符的起始X坐标
							usY：字符的起始Y坐标
							pStr: 要显示的字符串
** Returned value:          
** Created by:              zheh.zhang
** Created date:            2021-04-24
**--------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
****************************************************************************************************/
void ILI9341_DispString_EN_YDir(uint16_t usX, uint16_t usY, char *pStr)
{
	while(*pStr != '\0')
	{
		if((usX - ILI9341_DispWindow_X_Star + LCD_CurrentFonts->width) > LCD_X_LENGTH)
		{
			usX = ILI9341_DispWindow_X_Star;
			usY += LCD_CurrentFonts->height;
		}

		if((usY - ILI9341_DispWindow_Y_Star + LCD_CurrentFonts->height) > LCD_Y_LENGTH)
		{
			usX = ILI9341_DispWindow_X_Star;
			usY = ILI9341_DispWindow_Y_Star;
		}

		ILI9341_DispChar_EN(usX, usY, *pStr);

		pStr++;

		usY += LCD_CurrentFonts->height;
	}
}

void LCD_SetFont(sFont *fonts)
{
	LCD_CurrentFonts = fonts;
}

sFont *LCD_GetFont(void)
{
	return LCD_CurrentFonts;
}

void LCD_SetColors(uint16_t TextColor, uint16_t BackColor)
{
	CurrentTextColor = TextColor;
	CurrentBackColor = BackColor;
}

void LCD_GetColors(uint16_t *TextColor, uint16_t *BackColor)
{
	*TextColor = CurrentTextColor;
	*BackColor = CurrentBackColor;
}

void LCD_SetTextColor(uint16_t TextColor)
{
	CurrentTextColor = TextColor;
}

void LCD_SetBackColor(uint16_t BackColor)
{
	CurrentBackColor = BackColor;
}

void LCD_ClearLine(uint16_t line)
{
	ILI9341_Clear(0, line, LCD_X_LENGTH, ((sFont *)LCD_GetFont)->height);
}



